bitkeeper revision 1.1159.56.1 (412f28f2oorf9i_6akPMKOUodxF7qg)
authorkaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk>
Fri, 27 Aug 2004 12:28:34 +0000 (12:28 +0000)
committerkaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk>
Fri, 27 Aug 2004 12:28:34 +0000 (12:28 +0000)
Towards new device-interface setup code for the frontend drivers.
Added a synchronous send-and-get-response call to the control
interface API. Modified and extended the domain-controller messaging
protocol.

linux-2.6.8.1-xen-sparse/arch/xen/kernel/ctrl_if.c
linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c
linux-2.6.8.1-xen-sparse/include/asm-xen/ctrl_if.h
tools/python/xen/lowlevel/xu/xu.c
tools/python/xen/xend/server/netif.py
xen/include/hypervisor-ifs/io/domain_controller.h

index ef9958e3b70bbe4dab2539c3534a41fbd3d6eb50..40d29c70cb30caaa44d640aded151f82f48d2dca 100644 (file)
@@ -201,7 +201,8 @@ static irqreturn_t ctrl_if_interrupt(int irq, void *dev_id,
     return IRQ_HANDLED;
 }
 
-int ctrl_if_send_message_noblock(
+int
+ctrl_if_send_message_noblock(
     ctrl_msg_t *msg, 
     ctrl_msg_handler_t hnd,
     unsigned long id)
@@ -245,7 +246,8 @@ int ctrl_if_send_message_noblock(
     return 0;
 }
 
-int ctrl_if_send_message_block(
+int
+ctrl_if_send_message_block(
     ctrl_msg_t *msg, 
     ctrl_msg_handler_t hnd, 
     unsigned long id,
@@ -280,7 +282,59 @@ int ctrl_if_send_message_block(
     return rc;
 }
 
-int ctrl_if_enqueue_space_callback(struct tq_struct *task)
+/* Allow a reponse-callback handler to find context of a blocked requester.  */
+struct rsp_wait {
+    ctrl_msg_t         *msg;  /* Buffer for the response message.            */
+    struct task_struct *task; /* The task that is blocked on the response.   */
+    int                 done; /* Indicate to 'task' that response is rcv'ed. */
+};
+
+static void __ctrl_if_get_response(ctrl_msg_t *msg, unsigned long id)
+{
+    struct rsp_wait    *wait = (struct rsp_wait *)id;
+    struct task_struct *task = wait->task;
+
+    memcpy(wait->msg, msg, sizeof(*msg));
+    wmb();
+    wait->done = 1;
+
+    wake_up_process(task);
+}
+
+int
+ctrl_if_send_message_and_get_response(
+    ctrl_msg_t *msg, 
+    ctrl_msg_t *rmsg,
+    long wait_state)
+{
+    struct rsp_wait wait;
+    int rc;
+
+    wait.msg  = rmsg;
+    wait.done = 0;
+    wait.task = current;
+
+    if ( (rc = ctrl_if_send_message_block(msg, __ctrl_if_get_response,
+                                          (unsigned long)&wait,
+                                          wait_state)) != 0 )
+        return rc;
+
+    for ( ; ; )
+    {
+        /* NB. Can't easily support TASK_INTERRUPTIBLE here. */
+        set_current_state(TASK_UNINTERRUPTIBLE);
+        if ( wait.done )
+            break;
+        schedule();
+    }
+
+    set_current_state(TASK_RUNNING);
+    return 0;
+}
+
+int
+ctrl_if_enqueue_space_callback(
+    struct tq_struct *task)
 {
     control_if_t *ctrl_if = get_ctrl_if();
 
@@ -299,7 +353,9 @@ int ctrl_if_enqueue_space_callback(struct tq_struct *task)
     return TX_FULL(ctrl_if);
 }
 
-void ctrl_if_send_response(ctrl_msg_t *msg)
+void
+ctrl_if_send_response(
+    ctrl_msg_t *msg)
 {
     control_if_t *ctrl_if = get_ctrl_if();
     unsigned long flags;
@@ -327,7 +383,8 @@ void ctrl_if_send_response(ctrl_msg_t *msg)
     ctrl_if_notify_controller();
 }
 
-int ctrl_if_register_receiver(
+int
+ctrl_if_register_receiver(
     u8 type, 
     ctrl_msg_handler_t hnd, 
     unsigned int flags)
@@ -361,7 +418,10 @@ int ctrl_if_register_receiver(
     return !inuse;
 }
 
-void ctrl_if_unregister_receiver(u8 type, ctrl_msg_handler_t hnd)
+void 
+ctrl_if_unregister_receiver(
+    u8 type,
+    ctrl_msg_handler_t hnd)
 {
     unsigned long flags;
 
index 6e3d1ab6dc3d0837a15c4c77a31dfdd57b8d70d1..71105776b239ef9a012045c7347ee9540cf0f67a 100644 (file)
@@ -814,9 +814,10 @@ static void netif_driver_status_change(
     int err = 0;
     int i;
 
-    DPRINTK("> nr_interfaces=%d\n", status->nr_interfaces);
+    DPRINTK("> max_handle=%d\n", status->max_handle);
 
-    netctrl.interface_n = status->nr_interfaces;
+    /* XXX FIXME: Abuse of 'max_handle' as interface count. */
+    netctrl.interface_n = status->max_handle;
     netctrl.connected_n = 0;
 
     for ( i = 0; i < netctrl.interface_n; i++ )
@@ -913,7 +914,7 @@ static int __init netif_init(void)
     cmsg.subtype   = CMSG_NETIF_FE_DRIVER_STATUS_CHANGED;
     cmsg.length    = sizeof(netif_fe_driver_status_changed_t);
     st.status      = NETIF_DRIVER_STATUS_UP;
-    st.nr_interfaces = 0;
+    st.max_handle  = 0;
     memcpy(cmsg.msg, &st, sizeof(st));
     ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
 
@@ -999,7 +1000,7 @@ void netif_resume(void)
     cmsg.subtype   = CMSG_NETIF_FE_DRIVER_STATUS_CHANGED;
     cmsg.length    = sizeof(netif_fe_driver_status_changed_t);
     st.status      = NETIF_DRIVER_STATUS_UP;
-    st.nr_interfaces = 0;
+    st.max_handle  = 0;
     memcpy(cmsg.msg, &st, sizeof(st));
     ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
 #endif
index c90e010a03516c3b14b6683449958fa623f7e5dd..ad1dde646448d30b33ae9e15817217b518c74424 100644 (file)
@@ -37,7 +37,8 @@ typedef void (*ctrl_msg_handler_t)(ctrl_msg_t *, unsigned long);
  *     function returns.
  *  2. If @hnd is NULL then no callback is executed.
  */
-int ctrl_if_send_message_noblock(
+int
+ctrl_if_send_message_noblock(
     ctrl_msg_t *msg, 
     ctrl_msg_handler_t hnd,
     unsigned long id);
@@ -52,12 +53,23 @@ int ctrl_if_send_message_noblock(
  *     function returns.
  *  2. If @hnd is NULL then no callback is executed.
  */
-int ctrl_if_send_message_block(
+int
+ctrl_if_send_message_block(
     ctrl_msg_t *msg, 
     ctrl_msg_handler_t hnd, 
     unsigned long id, 
     long wait_state);
 
+/*
+ * Send @msg to the domain controller. Block until the response is received,
+ * and then copy it into the provided buffer, @rmsg.
+ */
+int
+ctrl_if_send_message_and_get_response(
+    ctrl_msg_t *msg,
+    ctrl_msg_t *rmsg,
+    long wait_state);
+
 /*
  * Request a callback when there is /possibly/ space to immediately send a
  * message to the domain controller. This function returns 0 if there is
@@ -65,7 +77,9 @@ int ctrl_if_send_message_block(
  * still be executed. If this function returns 1 then the callback /will/ be
  * executed when space becomes available.
  */
-int ctrl_if_enqueue_space_callback(struct tq_struct *task);
+int
+ctrl_if_enqueue_space_callback(
+    struct tq_struct *task);
 
 /*
  * Send a response (@msg) to a message from the domain controller. This will 
@@ -74,7 +88,9 @@ int ctrl_if_enqueue_space_callback(struct tq_struct *task);
  *  1. The @msg is copied and so can be freed after this function returns.
  *  2. The @msg may be the original request message, modified in-place.
  */
-void ctrl_if_send_response(ctrl_msg_t *msg);
+void
+ctrl_if_send_response(
+    ctrl_msg_t *msg);
 
 /*
  * Register a receiver for typed messages from the domain controller. The 
@@ -93,7 +109,9 @@ int ctrl_if_register_receiver(
  * Unregister a receiver for typed messages from the domain controller. The 
  * handler (@hnd) will not be executed after this function returns.
  */
-void ctrl_if_unregister_receiver(u8 type, ctrl_msg_handler_t hnd);
+void
+ctrl_if_unregister_receiver(
+    u8 type, ctrl_msg_handler_t hnd);
 
 /* Suspend/resume notifications. */
 void ctrl_if_suspend(void);
index c1c171383e4b3fa02edcc1c062fb35c02c4d8edf..f31d54b527ddc618f874e046d63cc1226365dd2f 100644 (file)
@@ -325,10 +325,10 @@ static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
     switch ( TYPE(xum->msg.type, xum->msg.subtype) )
     {
     case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(blkif_fe_driver_status_changed_t, nr_interfaces, u32);
+        P2C(blkif_fe_driver_status_changed_t, max_handle, u32);
         break;
     case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
+        P2C(netif_fe_driver_status_changed_t, max_handle, u32);
         break;
     }
 
@@ -435,7 +435,7 @@ static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
         return dict;
     case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
         C2P(netif_fe_driver_status_changed_t, status,        Int, Long);
-        C2P(netif_fe_driver_status_changed_t, nr_interfaces, Int, Long);
+        C2P(netif_fe_driver_status_changed_t, max_handle,    Int, Long);
         return dict;
     case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
         C2P(netif_fe_interface_connect_t, handle,         Int, Long);
@@ -630,7 +630,7 @@ static PyObject *xu_message_new(PyObject *self, PyObject *args)
         break;
     case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
         P2C(netif_fe_driver_status_changed_t, status,        u32);
-        P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
+        P2C(netif_fe_driver_status_changed_t, max_handle,    u32);
         break;
     }
 
index 1ba21698781ff9b2b24a53ae28786b156f37566a..be8140da80ebe3b463daea2a684cf8d9951c469a 100755 (executable)
@@ -333,8 +333,9 @@ class NetifController(controller.SplitController):
     def recv_fe_driver_status_changed(self, msg, req):
         if not req: return
         msg = packMsg('netif_fe_driver_status_changed_t',
-                      { 'status'        : NETIF_DRIVER_STATUS_UP,
-                        'nr_interfaces' : len(self.devices) })
+                      { 'status'     : NETIF_DRIVER_STATUS_UP,
+                        ## FIXME: max_handle should be max active interface id
+                        'max_handle' : len(self.devices) })
         self.writeRequest(msg)
         for dev in self.devices.values():
             dev.attach_fe_device()
index a7f3e4ee08978bccfa9e101fde67fe98296e8782..45090aca0fd5d28babc382de48302e4126eae450 100644 (file)
@@ -76,6 +76,7 @@ typedef struct {
 #define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED     32
 #define CMSG_BLKIF_FE_INTERFACE_CONNECT         33
 #define CMSG_BLKIF_FE_INTERFACE_DISCONNECT      34
+#define CMSG_BLKIF_FE_INTERFACE_QUERY           35
 
 /* These are used by both front-end and back-end drivers. */
 #define blkif_vdev_t   u16
@@ -87,7 +88,7 @@ typedef struct {
  *  Notify a guest about a status change on one of its block interfaces.
  *  If the interface is DESTROYED or DOWN then the interface is disconnected:
  *   1. The shared-memory frame is available for reuse.
- *   2. Any unacknowledged messgaes pending on the interface were dropped.
+ *   2. Any unacknowledged messages pending on the interface were dropped.
  */
 #define BLKIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
 #define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
@@ -103,10 +104,13 @@ typedef struct {
  * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
  *  Notify the domain controller that the front-end driver is DOWN or UP.
  *  When the driver goes DOWN then the controller will send no more
- *  status-change notifications. When the driver comes UP then the controller
- *  will send a notification for each interface that currently exists.
+ *  status-change notifications.
  *  If the driver goes DOWN while interfaces are still UP, the domain
  *  will automatically take the interfaces DOWN.
+ * 
+ *  NB. The controller should not send an INTERFACE_STATUS_CHANGED message
+ *  for interfaces that are active when it receives an UP notification. We
+ *  expect that the frontend driver will query those interfaces itself.
  */
 #define BLKIF_DRIVER_STATUS_DOWN   0
 #define BLKIF_DRIVER_STATUS_UP     1
@@ -114,11 +118,8 @@ typedef struct {
     /* IN */
     u32 status;        /*  0: BLKIF_DRIVER_STATUS_??? */
     /* OUT */
-    /*
-     * Tells driver how many interfaces it should expect to immediately
-     * receive notifications about.
-     */
-    u32 nr_interfaces; /*  4 */
+    /* Driver should query interfaces [0..max_handle]. */
+    u32 max_handle;    /*  4 */
 } PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
 
 /*
@@ -142,6 +143,18 @@ typedef struct {
     u32 handle; /*  0 */
 } PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */
 
+/*
+ * CMSG_BLKIF_FE_INTERFACE_QUERY:
+ */
+typedef struct {
+    /* IN */
+    u32 handle; /*  0 */
+    /* OUT */
+    u32 status; /*  4 */
+    u16 evtchn; /*  8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
+    domid_t domid; /* 10: status != BLKIF_INTERFACE_STATUS_DESTROYED */
+} PACKED blkif_fe_interface_query_t; /* 12 bytes */
+
 
 /******************************************************************************
  * BLOCK-INTERFACE BACKEND DEFINITIONS
@@ -332,6 +345,7 @@ typedef struct {
 #define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED     32
 #define CMSG_NETIF_FE_INTERFACE_CONNECT         33
 #define CMSG_NETIF_FE_INTERFACE_DISCONNECT      34
+#define CMSG_NETIF_FE_INTERFACE_QUERY           35
 
 /*
  * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
@@ -355,10 +369,13 @@ typedef struct {
  * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
  *  Notify the domain controller that the front-end driver is DOWN or UP.
  *  When the driver goes DOWN then the controller will send no more
- *  status-change notifications. When the driver comes UP then the controller
- *  will send a notification for each interface that currently exists.
+ *  status-change notifications.
  *  If the driver goes DOWN while interfaces are still UP, the domain
  *  will automatically take the interfaces DOWN.
+ * 
+ *  NB. The controller should not send an INTERFACE_STATUS_CHANGED message
+ *  for interfaces that are active when it receives an UP notification. We
+ *  expect that the frontend driver will query those interfaces itself.
  */
 #define NETIF_DRIVER_STATUS_DOWN   0
 #define NETIF_DRIVER_STATUS_UP     1
@@ -366,11 +383,8 @@ typedef struct {
     /* IN */
     u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
     /* OUT */
-    /*
-     * Tells driver how many interfaces it should expect to immediately
-     * receive notifications about.
-     */
-    u32        nr_interfaces; /*  4 */
+    /* Driver should query interfaces [0..max_handle]. */
+    u32        max_handle;    /*  4 */
 } PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
 
 /*
@@ -396,6 +410,19 @@ typedef struct {
     u32        handle;        /*  0 */
 } PACKED netif_fe_interface_disconnect_t; /* 4 bytes */
 
+/*
+ * CMSG_NETIF_FE_INTERFACE_QUERY:
+ */
+typedef struct {
+    /* IN */
+    u32        handle; /*  0 */
+    /* OUT */
+    u32        status; /*  4 */
+    u16        evtchn; /*  8: status == NETIF_INTERFACE_STATUS_CONNECTED */
+    u8         mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
+    domid_t    domid;  /* 16: status != NETIF_INTERFACE_STATUS_DESTROYED */
+} PACKED netif_fe_interface_query_t; /* 18 bytes */
+
 
 /******************************************************************************
  * NETWORK-INTERFACE BACKEND DEFINITIONS